package com.mytest.example.gobrs.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.gobrs.async.GobrsAsync;
import com.gobrs.async.domain.AsyncResult;
import com.gobrs.async.domain.TaskResult;
import com.gobrs.async.engine.RuleThermalLoad;
import com.gobrs.async.rule.Rule;
import com.mytest.example.gobrs.task.chain1.Chain1TaskA;
import com.mytest.example.gobrs.task.chain1.Chain1TaskB;
import com.mytest.example.gobrs.task.chain1.Chain1TaskC;
import com.mytest.example.gobrs.task.chain2.Chain2Param1;
import com.mytest.example.gobrs.task.chain2.Chain2TaskA;
import com.mytest.example.gobrs.task.chain2.Chain2TaskB;
import com.mytest.example.gobrs.task.chain3.Chain3Param1;
import com.mytest.example.gobrs.task.chain3.Chain3Param2;
import com.mytest.example.gobrs.task.chain3.Chain3TaskA;
import com.mytest.example.gobrs.task.chain3.Chain3TaskB;
import com.mytest.example.gobrs.task.chain4.Chain4Param1;
import com.mytest.example.gobrs.task.chain4.Chain4TaskA;
import com.mytest.example.gobrs.task.chain4.Chain4TaskB;
import com.mytest.example.gobrs.task.chain5.Chain5Param1;
import com.mytest.example.gobrs.task.chain5.Chain5TaskA;
import com.mytest.example.gobrs.task.chain5.Chain5TaskB;
import com.mytest.example.gobrs.task.chain6.Chain6Param1;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Slf4j
@RequestMapping("/task")
@RestController
public class TaskController {
    @Autowired
    private GobrsAsync gobrsAsync;
    @Resource
    private RuleThermalLoad ruleThermalLoad;

    /**
     * 无参数传递的任务链
     */
    @GetMapping("/executeWithoutParam")
    public String executeWithoutParam(HttpServletRequest request) {
        Map<String, Object> params = new HashMap<>();
        AsyncResult asyncResult = gobrsAsync.go("chain1", () -> params);
        String result1 = asyncResult.getResultMap().get(Chain1TaskA.class).getResult().toString();
        String result2 = asyncResult.getResultMap().get(Chain1TaskB.class).getResult().toString();
        String result3 = asyncResult.getResultMap().get(Chain1TaskC.class).getResult().toString();
        return StrUtil.format("chain1 result={},{},{}", result1, result2, result3);
    }

    /**
     * 带有参数传递的任务链
     * 多个任务使用同一个参数
     *
     * @param request
     * @return
     */
    @GetMapping("/executeWithParam1")
    public String executeWithParam1(HttpServletRequest request) {
        String uid = request.getParameter("uid");
        Chain2Param1 params = new Chain2Param1();
        params.setUid(uid);
        AsyncResult asyncResult = gobrsAsync.go("chain2", () -> params);
        String result1 = asyncResult.getResultMap().get(Chain2TaskA.class).getResult().toString();
        String result2 = asyncResult.getResultMap().get(Chain2TaskB.class).getResult().toString();
        return StrUtil.format("chain2 result={},{}", result1, result2);
    }

    /**
     * 带有参数传递的任务链
     * 多个任务使用不同的参数
     *
     * @param request
     * @return
     */
    @GetMapping("/executeWithParam2")
    public String executeWithParam2(HttpServletRequest request) {
        String uid = request.getParameter("uid");
        String ticket = request.getParameter("ticket");

        Chain3Param1 p1 = new Chain3Param1();
        p1.setUid(uid);
        Chain3Param2 p2 = new Chain3Param2();
        p2.setTicket(ticket);

        Map<Object, Object> params = new HashMap<>();
        params.put(Chain3TaskA.class, p1);
        params.put(Chain3TaskB.class, p2);
        AsyncResult asyncResult = gobrsAsync.go("chain3", () -> params);
        String result1 = asyncResult.getResultMap().get(Chain3TaskA.class).getResult().toString();
        String result2 = asyncResult.getResultMap().get(Chain3TaskB.class).getResult().toString();
        return StrUtil.format("chain3 result={},{}", result1, result2);
    }


    /**
     * 跳过链条中的任务
     *
     * @param request
     * @return
     */
    @GetMapping("/executeWhileSkipTask")
    public String executeWhileSkipTask(HttpServletRequest request) {
        String cancel = request.getParameter("cancel");
        String shouldThrow = request.getParameter("shouldThrow");
        Chain4Param1 params = new Chain4Param1();
        if (StrUtil.isNotEmpty(cancel)) {
            params.setCancel(Boolean.parseBoolean(cancel));
        }
        if (StrUtil.isNotEmpty(shouldThrow)) {
            params.setShouldThrow(Boolean.parseBoolean(shouldThrow));
        }
        AsyncResult asyncResult = gobrsAsync.go("chain4", () -> params);
        log.info("asyncResult={}", JSON.toJSONString(asyncResult));
        String result1 = asyncResult.getResultMap().get(Chain4TaskA.class).getResult().toString();
        String result = StrUtil.format("chain4 result={}", result1);
        if (!params.getCancel()) {
            TaskResult result2 = asyncResult.getResultMap().get(Chain4TaskB.class);
            if (ObjectUtil.isNotNull(result2.getResult())) {
                result = result + "," + result2.getResult();
            }
        }
        return result;
    }


    @GetMapping("/executeWithTimeout")
    public String executeWithTimeout(HttpServletRequest request) {
        Chain5Param1 params = new Chain5Param1();
        String timeout = request.getParameter("timeout");
        if (StrUtil.isNotEmpty(timeout)) {
            params.setTimeout(Convert.toInt(timeout));
        }
        long timeoutMillis = TimeUnit.SECONDS.toMillis(15L);
        try {
            AsyncResult asyncResult = gobrsAsync.go("chain5", () -> params, timeoutMillis);
            log.info("executeWithTimeout:asyncResult={}", JSON.toJSONString(asyncResult));
            if (asyncResult.isSuccess()) {
                String result1 = asyncResult.getResultMap().get(Chain5TaskA.class).getResult().toString();
                String result2 = asyncResult.getResultMap().get(Chain5TaskB.class).getResult().toString();
                return StrUtil.format("chain5 result={},{}", result1, result2);
            } else {
                return "任务执行失败";
            }
        } catch (com.gobrs.async.exception.TimeoutException ex) {
            ex.printStackTrace();
            return "任务执行超时";
        }
    }


    @GetMapping("/executeBeforeUpdateRule")
    public String executeBeforeUpdateRule(HttpServletRequest request) {
        Chain6Param1 params = new Chain6Param1();
        params.setChain("start ");
        AsyncResult asyncResult = gobrsAsync.go("chain6", () -> params);
        params.setChain(params.getChain() + " ->end");
        return StrUtil.format("chain6 result={}", params.getChain());
    }

    @GetMapping("/hotUpdateTaskRue")
    public String hotUpdateTaskRue(HttpServletRequest request) {
// 单任务修改
        Rule r = new Rule();
        r.setName("chain6");
        //chain6TaskA->chain6TaskB->chain6TaskC
        r.setContent("chain6TaskC->chain6TaskB->chain6TaskA");
        ruleThermalLoad.load(r);

        // 批量修改
        //List<Rule> updateRules = new ArrayList<>();
        //updateRules.add(r);
        // updateRules.add(...);
        //ruleThermalLoad.load(updateRules);
        return "修改成功";
    }
}
